package com.example.seckill.service.impl;

import com.example.seckill.entity.Product;
import com.example.seckill.mapper.ProductMapper;
import com.example.seckill.service.IProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Ding
 * @since 2022-04-25
 */
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService {
    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplate;

    @Override
    public synchronized int doSecKill(Integer uid, String productId) {
        //1、uid和productId非空判断，如果是空，则返回-1
        if (uid == null || productId == null) {
            return -4;
        }
        //2、拼接key（目标商品库存 & 目标商品下单人数）
        String kcKey = "sk:" + productId + ":qt";
        String userKey = "sk:" + productId + ":user";

        //3、获取库存，若是null，说明商品不在redis缓存中，也就是不在秒杀中，返回-2
        int kc = redisTemplate.opsForValue().get(kcKey) == null ? -2 : Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(kcKey)));
        if (kc == -2) {
            //查无此商品，无法秒杀
            return -2;
        }
        if (kc == -1) {
            //秒杀还没有开始，请等待，-1是默认添加的值，代表添加到秒杀区，但是还没开始
            return -1;
        }
        //4、判断用户是否已经秒杀成功过了
        if (redisTemplate.opsForSet().isMember(userKey, uid)) {
            //如果uid在对应商品Set无序集合中，说明已经秒杀过了，不能重复秒杀
            return -3;
        }
        //5、如果库存数量小于1，抢光了，提示秒杀结束，后台可以进行下架，然后再次查询其状态就会变成-2
        if (kc <=0) {
            //秒杀结束
            return 0;
        }
        //6、一切准备就绪，①减库存，②加入秒杀成功的用户Set
        redisTemplate.opsForValue().decrement(kcKey);
        redisTemplate.opsForSet().add(userKey, uid);
        return 1;
    }

    @Override
    public List<Map<String, Object>> getSeckillList() {
        //1、获取所有的秒杀商品
        Set<String> keys = redisTemplate.keys("sk:*:qt");
        List<Map<String, Object>> list = new ArrayList<>();
        //2、遍历所有的秒杀商品
        for (String key : keys) {
            Map<String, Object> map = new HashMap<>();
            //拆分获取productId
            map.put("productId", key.split(":")[1]);
            //获取key的value即库存数量
            map.put("num", redisTemplate.opsForValue().get(key));
            //获取TTL即有效期
            map.put("time",redisTemplate.getExpire(key));
            list.add(map);
        }
        return list;
    }

    @Override
    public boolean toAddItem(String productId) {
        if (redisTemplate.opsForValue().get("sk:" + productId + ":qt") == null) {
            //不存在，添加到redis缓存
            redisTemplate.opsForValue().set("sk:" + productId + ":qt",-1);
            return true;
        }
        //如果已经存在，则不添加
        return false;
    }

    @Override
    public boolean beginKill(String productId, Integer num, String time) {
        //重写该商品信息（赋予生存时间和数量），开放秒杀
        redisTemplate.opsForValue().set("sk:" + productId + ":qt",num,Long.parseLong(time), TimeUnit.SECONDS);
        return true;
    }

    @Override
    public boolean endKill(String productId) {
        //下架商品，不再秒杀
        redisTemplate.delete("sk:" + productId + ":qt");
        return true;
    }
}
